package com.whjfxx.terminal.biz.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.whjfxx.terminal.biz.enums.YesNoEnum;
import com.whjfxx.terminal.biz.mapper.PoImportLogMapper;
import com.whjfxx.terminal.biz.param.ImportPageParam;
import com.whjfxx.terminal.biz.param.SearchParam;
import com.whjfxx.terminal.biz.service.PoImportDataService;
import com.whjfxx.terminal.biz.service.PoImportLogService;
import com.whjfxx.terminal.biz.vo.ImportDataVo;
import com.whjfxx.terminal.biz.vo.ImportVo;
import com.whjfxx.terminal.commons.Content;
import com.whjfxx.terminal.entity.PoImportData;
import com.whjfxx.terminal.entity.PoImportLog;
import com.whjfxx.terminal.exceptions.BizException;
import com.whjfxx.terminal.utils.PageUtils;
import com.whjfxx.terminal.utils.QueryUtil;
import jodd.util.StringUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by b.c on 2022/6/7 16:28
 */
@Service
public class PoImportLogServiceImpl extends ServiceImpl<PoImportLogMapper, PoImportLog> implements PoImportLogService {


    @Autowired
    PoImportDataService poImportDataService;

    @Override
    public Page<ImportVo> pageList(SearchParam<ImportPageParam> param) {
        LambdaQueryWrapper<PoImportLog> wrapper = new LambdaQueryWrapper<>();
        QueryUtil.search(param,ImportPageParam.class, searchParam -> {
            if (StringUtils.isNotBlank(searchParam.getBatchNo())) {
                wrapper.like(PoImportLog::getBatchNo, searchParam.getBatchNo());
            }
        });

        wrapper.orderByDesc(PoImportLog::getCreateTime);
        this.page(param, wrapper);
        Page<PoImportLog> page = PageUtils.buildPage(param);

        Page<ImportVo> voPage = PageUtils.convert(page, ImportVo.class, (src, target) -> {
            String url = "terminal/" + src.getUrl();
            target.setUrl(url);
        });
        return voPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importXlsx(MultipartFile multipartFile, XSSFWorkbook workbook) throws IOException {
        // 保存文件
        String url = "terminal/" + System.currentTimeMillis()  + getPrefixName(multipartFile.getOriginalFilename());
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String batchNo = "B" + LocalDateTime.now().format(dtf) + System.currentTimeMillis();
        File file = new File(Content.FileConfig.BASE_PATH + url);


        multipartFile.transferTo(file);
        PoImportLog importLog = new PoImportLog();
        importLog.setBatchNo(batchNo);
        importLog.setFileName(multipartFile.getOriginalFilename());
        importLog.setFileSize(multipartFile.getSize());
        importLog.setDataSize((long)workbook.getSheetAt(0).getLastRowNum());
        importLog.setUrl(url);
        importLog.setDataStatus(0);
        importLog.setCreateTime(LocalDateTime.now());
        importLog.setUpdateTime(LocalDateTime.now());
        this.save(importLog);
        this.saveData(batchNo, workbook);

        return batchNo;
    }

    private void saveData(String batchNo, XSSFWorkbook workbook) {
        Sheet sheet = workbook.getSheetAt(0);
        Row row0 = sheet.getRow(0);
        int i = 0;
        while(i <= 10) {
            Cell headerCell = row0.getCell(i);
            String cellValue = this.getStringCellValue(headerCell);
            if (Objects.isNull(headerCell) || !Content.TERMINAL_IMPORT_HEADER[i].equals(cellValue)) {
                throw BizException.build("文件模板数据不正确");
            }
            i++;
        }
        // 读取内容
        List<PoImportData> importDatas = new ArrayList<>();
        int rowIndex = 1;
        while(true) {
            Row row = sheet.getRow(rowIndex);
            if (Objects.isNull(row)) {
                break;
            }

            ImportDataVo importTerminal = new ImportDataVo();
            String organizationCode = getStringCellValue(row.getCell(0));
            String appName = getStringCellValue(row.getCell(1));
            String funcName = getStringCellValue(row.getCell(2));
            String sn = getStringCellValue(row.getCell(3));
            String terminalType = getStringCellValue(row.getCell(4));
            String expiryType = getStringCellValue(row.getCell(5));
            String never = getStringCellValue(row.getCell(6));
            String activeStatus = getStringCellValue(row.getCell(7));
            String custName = getStringCellValue(row.getCell(8));
            String custMobile = getStringCellValue(row.getCell(9));
            String position = getStringCellValue(row.getCell(10));
            String area = getStringCellValue(row.getCell(11));


            importTerminal.setOrganizationCode(organizationCode);
            importTerminal.setAppName(appName);
            importTerminal.setFuncName(funcName);
            importTerminal.setSn(sn);
            importTerminal.setTerminalType(terminalType);
            importTerminal.setExpiryType(expiryType);
            importTerminal.setNever(never);
            importTerminal.setActiveStatus(activeStatus);
            importTerminal.setCustName(custName);
            importTerminal.setCustMobile(custMobile);
            importTerminal.setPosition(position);
            importTerminal.setArea(area);
            importTerminal.setDataStatus(YesNoEnum.NO.status);

            PoImportData importData = new PoImportData();
            importData.setBatchNo(batchNo);
            importData.setStatus(0);
            importData.setData(JSONObject.toJSONString(importTerminal));
            importData.setCreateTime(LocalDateTime.now());
            importDatas.add(importData);
            rowIndex++;
        }

        if (CollectionUtils.isNotEmpty(importDatas)) {
            this.poImportDataService.saveBatch(importDatas);
        }
    }

    @Override
    public List<ImportDataVo> readXlsx(String batchNo) {
        if (StringUtil.isBlank(batchNo)) {
            return Collections.emptyList();
        }
        // 保存文件
        LambdaQueryWrapper<PoImportLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PoImportLog::getBatchNo, batchNo);
        PoImportLog poImportLog = this.getOne(wrapper);
        if (Objects.isNull(poImportLog)) {
            return Collections.emptyList();
        }


        try {
            File file = new File(Content.FileConfig.BASE_PATH + poImportLog.getUrl());
            XSSFWorkbook workbook = new XSSFWorkbook(file);
            Sheet sheet = workbook.getSheetAt(0);
            // 读取第一行数据，数据必须是  "应用名称", "功能名称", "序列号(SN)", "型号", "位置", "应用版本号","功能版本"

            Row row0 = sheet.getRow(0);
            int i = 0;
            while(i <= 10) {
                Cell headerCell = row0.getCell(i);
                String cellValue = this.getStringCellValue(headerCell);
                if (Objects.isNull(headerCell) || !Content.TERMINAL_IMPORT_HEADER[i].equals(cellValue)) {
                    throw BizException.build("文件模板数据不正确");
                }
                i++;
            }
            // 读取内容
            List<ImportDataVo> importTerminals = new ArrayList<>();
            int rowIndex = 1;
            while(true) {
                Row row = sheet.getRow(rowIndex);
                if (Objects.isNull(row)) {
                    break;
                }

                ImportDataVo importTerminal = new ImportDataVo();

                String organizationCode = getStringCellValue(row.getCell(0));
                String appName = getStringCellValue(row.getCell(1));
                String funcName = getStringCellValue(row.getCell(2));
                String sn = getStringCellValue(row.getCell(3));
                String terminalType = getStringCellValue(row.getCell(4));
                String expiryType = getStringCellValue(row.getCell(5));
                String never = getStringCellValue(row.getCell(6));
                String activeStatus = getStringCellValue(row.getCell(7));
                String custName = getStringCellValue(row.getCell(8));
                String custMobile = getStringCellValue(row.getCell(9));
                String position = getStringCellValue(row.getCell(10));
                String area = getStringCellValue(row.getCell(11));

                importTerminal.setId((long)rowIndex);
                importTerminal.setOrganizationCode(organizationCode);
                importTerminal.setAppName(appName);
                importTerminal.setFuncName(funcName);
                importTerminal.setSn(sn);
                importTerminal.setTerminalType(terminalType);
                importTerminal.setExpiryType(expiryType);
                importTerminal.setNever(never);
                importTerminal.setActiveStatus(activeStatus);
                importTerminal.setCustName(custName);
                importTerminal.setCustMobile(custMobile);
                importTerminal.setPosition(position);
                importTerminal.setArea(area);
                importTerminal.setDataStatus(YesNoEnum.NO.status);
                importTerminals.add(importTerminal);
                rowIndex++;
            }
            return importTerminals;
        } catch (Exception e) {
            e.printStackTrace();
            throw BizException.build("读取文件失败", "读取导入文件[" + poImportLog.getId() + "]失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void valid(String batchNo) {

    }

    @Override
    public void importData(String batchNo) {
        Objects.requireNonNull(batchNo);
        LambdaQueryWrapper<PoImportLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PoImportLog::getBatchNo, batchNo);
        PoImportLog importLog = this.getOne(wrapper);
        if (Objects.isNull(importLog)) {
            throw BizException.build("查询批次数据错误");
        }

        // 导入明细数据
        LambdaQueryWrapper<PoImportData> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(PoImportData::getBatchNo, batchNo);
        wrapper1.eq(PoImportData::getStatus, YesNoEnum.NO.status);
        List<PoImportData> poImportDatas = poImportDataService.list(wrapper1);
        if (CollectionUtils.isEmpty(poImportDatas)) {
            // 设置状态处理中
            importLog.setDataStatus(3);
            importLog.setUpdateTime(LocalDateTime.now());
            this.updateById(importLog);
            return;
        }

        // 设置状态处理中
        importLog.setDataStatus(1);
        importLog.setUpdateTime(LocalDateTime.now());
        this.updateById(importLog);

        int success = 0, err = 0;
        for (PoImportData poImportData : poImportDatas) {
            try {
                poImportData = poImportDataService.importData(poImportData);
                success++;
            } catch (Exception e) {
                e.printStackTrace();
                String msg = e.getMessage();
                if (msg.length() > 300) {
                    msg = msg.substring(0, 300);
                }
                poImportData.setMsg(msg);
                poImportData.setStatus(YesNoEnum.ERR.status);
                poImportDataService.updateById(poImportData);
                err++;
            }
        }

        // 设置完成
        if (err == 0) {
            // 设置状态处理中
            importLog.setDataStatus(3);
            importLog.setUpdateTime(LocalDateTime.now());
            this.updateById(importLog);
        } else if (err > 0 && success > 0) {
            // 设置状态处理中
            importLog.setDataStatus(2);
            importLog.setUpdateTime(LocalDateTime.now());
            this.updateById(importLog);
        }  else if (err > 0 && success == 0) {
            // 设置状态处理中
            importLog.setDataStatus(4);
            importLog.setUpdateTime(LocalDateTime.now());
            this.updateById(importLog);
        }
    }

    private String getStringCellValue(Cell cell) {
        if (Objects.isNull(cell)) {
            return null;
        }
        if (cell.getCellType() == CellType.NUMERIC) {
            if (Objects.isNull(cell.getNumericCellValue())) {
                return null;
            } else {
                return cell.getNumericCellValue() + "";
            }
        }
        if (cell.getCellType() == CellType.STRING) {
            return cell.getStringCellValue();
        }
        return null;
    }

    private String getPrefixName(String fileName) {
        return fileName.substring(fileName.lastIndexOf("."));
    }
}
